﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Service;
using MODEL;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using GalaSoft.MvvmLight.Views;
using Common;
using System.ComponentModel;
using GalaSoft.MvvmLight.Ioc;
using System.Windows.Threading;

namespace ViewModel.StationControl
{
    public class ValveControlViewModel : ViewModelBase
    {
        public ICommand StartProcessCommand { get; set; }

        public ICommand UpgradeSequenceCommand { get; set; }

        public ICommand DegradeSequenceCommand { get; set; }

        public ICommand RemoveFromSequenceCommand { get; set; }

        private DispatcherTimer dispatcherTimer = new DispatcherTimer();

        private DateTime m_StartDate = DateTime.Now.Date;
        public DateTime StartDate
        {
            get { return m_StartDate; }
            set { m_StartDate = value; base.RaisePropertyChanged(() => StartDate); }
        }


        private ProcessStatusEnum m_ProcessStatus;
        private ProcessStatusEnum ProcessStatus
        {
            get { return this.m_ProcessStatus; }
            set { this.m_ProcessStatus = value; base.RaisePropertyChanged(() => this.IsInProcess); base.RaisePropertyChanged(() => IsWaitProcess); base.RaisePropertyChanged(() => IsNoProcess); }
        }
       
        public bool IsInProcess => ProcessStatus == ProcessStatusEnum.InProcess;

        public bool IsWaitProcess => ProcessStatus == ProcessStatusEnum.Wait;

        public bool IsNoProcess => ProcessStatus == ProcessStatusEnum.None;

        private StationInfo m_StationInfo;
        public StationInfo StationInfo
        {
            get { return m_StationInfo; }
            set { this.m_StationInfo = value; base.RaisePropertyChanged(() => this.StationInfo); }
        }

        private List<ProcessModel> m_ProcessModelList;
        public List<ProcessModel> ProcessModelList
        {
            get { return m_ProcessModelList; }
            set { this.m_ProcessModelList = value; base.RaisePropertyChanged(() => ProcessModelList); }
        }

        private List<ValveControl> m_ProcessValveControlList;
        public List<ValveControl> ProcessValveControlList
        {
            get { return this.m_ProcessValveControlList; }
            set { this.m_ProcessValveControlList = value; base.RaisePropertyChanged(() => this.ProcessValveControlList); }
        }

        private List<ValveControl> m_ValveControlRecords;
        public List<ValveControl> ValveControlRecords
        {
            get { return this.m_ValveControlRecords; }
            set { this.m_ValveControlRecords = value; base.RaisePropertyChanged(() => this.ValveControlRecords); }
        }

        private IValveControlService m_ValveControlService;

        public ValveControlViewModel(IValveControlService valveControlService)
        {
            this.m_ValveControlService = valveControlService;
            this.PropertyChanged += OnPropertyChange;

            this.StartProcessCommand = new RelayCommand(StartProcess);
            this.UpgradeSequenceCommand = new RelayCommand<ValveControl>(UpgradeValveSequence);
            this.DegradeSequenceCommand = new RelayCommand<ValveControl>(DegradeValveSequence);
            this.RemoveFromSequenceCommand = new RelayCommand<ValveControl>(RemoveValveFormSequence);

            dispatcherTimer.Tick += new EventHandler(DispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
            dispatcherTimer.Start();            
        }

        public void DispatcherTimer_Tick(object sender, EventArgs e)
        {
            if (this.IsNoProcess)
            {
                return;
            }

            if (!this.ProcessModelList.SafeCheck())
            {
                this.ProcessStatus = ProcessStatusEnum.None;
                return;
            }

            this.ProcessModelList.ForEach(p => p.ProcessItem?.RaiseUIProperty());

            if (ProcessModelList.All(p => p.ProcessItem.ProcessStatus == ProcessStatusEnum.Wait))
            {
                this.ProcessStatus = ProcessStatusEnum.Wait;
            }
            else if (ProcessModelList.Any(p => p.ProcessItem.ProcessStatus == ProcessStatusEnum.InProcess || p.ProcessItem.ProcessStatus == ProcessStatusEnum.Wait))
            {
                this.ProcessStatus = ProcessStatusEnum.InProcess;
            }
            else
            {
                this.ProcessStatus = ProcessStatusEnum.None;
            }
        }

        public void InitialByStationInfo()
        {
            if (this.StationInfo == null || string.IsNullOrWhiteSpace(this.StationInfo.Valve_NoListStr) || this.StationInfo.ValveNoList.Count < 1)
            {
                this.ProcessStatus = ProcessStatusEnum.None;
                return;
            }

            this.ValveControlRecords = this.m_ValveControlService.QueryControlValues(new ValveControlQueryCriteria { StationId = this.StationInfo.StationId }).Result.ToList();

            if (this.ValveControlRecords.SafeCheck())
            {
                DateTime latestInsertTime = this.ValveControlRecords.Max(v => v.AddTime);
                List<ValveControl> latestValveControls = this.ValveControlRecords.Where(v => v.AddTime == latestInsertTime).ToList();

                if (latestValveControls.Any(v => v.IsInProcess))
                {
                    this.ProcessValveControlList = latestValveControls.OrderBy(v => v.Exec_Time).ToList();

                    if (ProcessValveControlList.SafeCheck())
                    {
                        this.ProcessStatus = ProcessStatusEnum.Wait;
                        this.StartDate = ProcessValveControlList.Min(m => m.Exec_Time);
                        this.ProcessModelList = ProcessValveControlList.Select(v => new ProcessModel
                        {
                            Name = $"第{ProcessValveControlList.IndexOf(v) + 1}阶段",                            
                            ProcessItem = v.ConvertToProcessItem()
                        }).ToList();
                    }
                }
            }

            if (!ProcessValveControlList.SafeCheck())
            { 
                this.ProcessStatus = ProcessStatusEnum.None;
                this.ProcessValveControlList = this.StationInfo.ValveNoList.OrderBy(v => v).Select(v => new ValveControl
                {
                    StationInfo = this.StationInfo,
                    Operator = AppSetting.Instance.User.UserId,                    
                    Valve_No = v
                }).ToList();
            }
        }

        public void OnPropertyChange(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "StationInfo")
            {
                InitialByStationInfo();
            }
        }

        public async void StartProcess()
        {
            if (this.StationInfo == null)
            {
                return;
            }

            if (this.ProcessStatus != ProcessStatusEnum.None)
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("当前站点正在执行", "提示");
                return;
            }

            DateTime now = DateTime.Now;
                        
            List<ValveControl> valveControls = this.ProcessValveControlList;
            valveControls.ForEach(v =>
            {
                DateTime startTime = this.StartDate + v.Exec_TimeSpan;
                startTime = (startTime > now ? startTime : now) + AppSetting.Instance.ValveControlBeginDelayTime;
                v.Exec_Time = startTime;
                v.AddTime = now;
                v.Update_Time = now;
            });

            this.m_ValveControlService.InsertControlValues(valveControls);
            this.InitialByStationInfo();
        }

        private void UpgradeValveSequence(ValveControl valve)
        {
            int index = this.ProcessValveControlList.IndexOf(valve);
            if (index == 0)
            {
                return;
            }
            this.ProcessValveControlList = IListHelper.replaceListIndex(this.ProcessValveControlList, index, index - 1).ToList();
        }

        private void DegradeValveSequence(ValveControl valve)
        {
            int index = this.ProcessValveControlList.IndexOf(valve);
            if (index == this.ProcessValveControlList.Count - 1)
            {
                return;
            }
            this.ProcessValveControlList = IListHelper.replaceListIndex(this.ProcessValveControlList, index, index + 1).ToList();
        }

        private void RemoveValveFormSequence(ValveControl valve)
        {
            List<ValveControl> valveControlList = new List<ValveControl>();

            valveControlList.AddRange(this.ProcessValveControlList);
            valveControlList.Remove(valve);
            this.ProcessValveControlList = valveControlList;
        }
    }
}
